#ifndef FILE_UTILS_H
#define FILE_UTILS_H

#include <filesystem>
#include <string>
#include <vector>
#include <regex>
#include <iostream>
#include <fstream>
#include <system_error>

namespace fs = std::filesystem;

class FileUtils {
public:
    // 操作结果结构体
    struct OperationResult {
        bool success;
        std::string message;
        
        OperationResult(bool s = true, const std::string& msg = "") 
            : success(s), message(msg) {}
    };

private:
    // 递归拷贝目录的辅助函数
    OperationResult copy_directory_recursive(const fs::path& source, const fs::path& destination) {
        try {
            // 创建目标目录
            if (!fs::exists(destination)) {
                fs::create_directories(destination);
            }
            
            // 遍历源目录中的所有项
            for (const auto& entry : fs::directory_iterator(source)) {
                const fs::path& src_path = entry.path();
                const fs::path dst_path = destination / src_path.filename();
                
                if (fs::is_directory(src_path)) {
                    // 递归拷贝子目录
                    auto result = copy_directory_recursive(src_path, dst_path);
                    if (!result.success) {
                        return result;
                    }
                } else {
                    // 拷贝文件
                    std::error_code ec;
                    fs::copy_file(src_path, dst_path, fs::copy_options::overwrite_existing, ec);
                    if (ec) {
                        return OperationResult(false, "Failed to copy file: " + src_path.string() + " - " + ec.message());
                    }
                }
            }
            
            return OperationResult(true, "Directory copied successfully");
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during directory copy: " + std::string(e.what()));
        }
    }
    
    // 递归搜索文件的辅助函数
    void search_files_recursive(const fs::path& directory, 
                               const std::regex& pattern, 
                               std::vector<std::string>& results,
                               bool recursive = true) {
        try {
            if (!fs::exists(directory) || !fs::is_directory(directory)) {
                return;
            }
            
            if (recursive) {
                // 使用递归迭代器
                for (const auto& entry : fs::recursive_directory_iterator(directory)) {
                    if (fs::is_regular_file(entry)) {
                        std::string filename = entry.path().filename().string();
                        if (std::regex_match(filename, pattern)) {
                            results.push_back(fs::absolute(entry.path()).string());
                        }
                    }
                }
            } else {
                // 使用非递归迭代器
                for (const auto& entry : fs::directory_iterator(directory)) {
                    if (fs::is_regular_file(entry)) {
                        std::string filename = entry.path().filename().string();
                        if (std::regex_match(filename, pattern)) {
                            results.push_back(fs::absolute(entry.path()).string());
                        }
                    }
                }
            }
        } catch (const std::exception& e) {
            std::cerr << "Error during file search: " << e.what() << std::endl;
        }
    }

public:
    // 1. 拷贝文件或目录
    OperationResult copy(const std::string& source, const std::string& destination) {
        try {
            fs::path src_path(source);
            fs::path dst_path(destination);
            
            if (!fs::exists(src_path)) {
                return OperationResult(false, "Source does not exist: " + source);
            }
            
            if (fs::is_directory(src_path)) {
                return copy_directory_recursive(src_path, dst_path);
            } else {
                // 如果目标是目录，则在其中创建同名文件
                if (fs::exists(dst_path) && fs::is_directory(dst_path)) {
                    dst_path = dst_path / src_path.filename();
                }
                
                // 确保目标目录存在
                fs::create_directories(dst_path.parent_path());
                
                std::error_code ec;
                fs::copy_file(src_path, dst_path, fs::copy_options::overwrite_existing, ec);
                if (ec) {
                    return OperationResult(false, "Failed to copy file: " + ec.message());
                }
                
                return OperationResult(true, "File copied successfully");
            }
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during copy: " + std::string(e.what()));
        }
    }
    
    // 2. 移动文件或目录
    OperationResult move(const std::string& source, const std::string& destination) {
        try {
            fs::path src_path(source);
            fs::path dst_path(destination);
            
            if (!fs::exists(src_path)) {
                return OperationResult(false, "Source does not exist: " + source);
            }
            
            // 如果目标是已存在的目录，则移动到该目录中
            if (fs::exists(dst_path) && fs::is_directory(dst_path)) {
                dst_path = dst_path / src_path.filename();
            }
            
            // 确保目标目录存在
            fs::create_directories(dst_path.parent_path());
            
            std::error_code ec;
            fs::rename(src_path, dst_path, ec);
            if (ec) {
                return OperationResult(false, "Failed to move: " + ec.message());
            }
            
            return OperationResult(true, "Moved successfully");
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during move: " + std::string(e.what()));
        }
    }
    
    // 3. 删除文件或目录
    OperationResult remove(const std::string& path) {
        try {
            fs::path target_path(path);
            
            if (!fs::exists(target_path)) {
                return OperationResult(false, "Path does not exist: " + path);
            }
            
            std::error_code ec;
            std::uintmax_t removed_count;
            
            if (fs::is_directory(target_path)) {
                removed_count = fs::remove_all(target_path, ec);
            } else {
                removed_count = fs::remove(target_path, ec) ? 1 : 0;
            }
            
            if (ec) {
                return OperationResult(false, "Failed to remove: " + ec.message());
            }
            
            return OperationResult(true, "Removed successfully (" + std::to_string(removed_count) + " items)");
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during remove: " + std::string(e.what()));
        }
    }
    
    // 4. 创建文件
    OperationResult create_file(const std::string& file_path, const std::string& content = "") {
        try {
            fs::path target_path(file_path);
            
            // 确保目录存在
            fs::create_directories(target_path.parent_path());
            
            std::ofstream file(target_path);
            if (!file.is_open()) {
                return OperationResult(false, "Failed to create file: " + file_path);
            }
            
            if (!content.empty()) {
                file << content;
            }
            
            file.close();
            return OperationResult(true, "File created successfully");
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during file creation: " + std::string(e.what()));
        }
    }
    
    // 5. 创建目录
    OperationResult create_directory(const std::string& dir_path) {
        try {
            fs::path target_path(dir_path);
            
            std::error_code ec;
            bool created = fs::create_directories(target_path, ec);
            
            if (ec) {
                return OperationResult(false, "Failed to create directory: " + ec.message());
            }
            
            if (created) {
                return OperationResult(true, "Directory created successfully");
            } else {
                return OperationResult(true, "Directory already exists");
            }
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during directory creation: " + std::string(e.what()));
        }
    }
    
    // 6. 重命名文件或目录
    OperationResult rename(const std::string& old_path, const std::string& new_name) {
        try {
            fs::path src_path(old_path);
            
            if (!fs::exists(src_path)) {
                return OperationResult(false, "Source does not exist: " + old_path);
            }
            
            fs::path new_path = src_path.parent_path() / new_name;
            
            std::error_code ec;
            fs::rename(src_path, new_path, ec);
            if (ec) {
                return OperationResult(false, "Failed to rename: " + ec.message());
            }
            
            return OperationResult(true, "Renamed successfully");
            
        } catch (const std::exception& e) {
            return OperationResult(false, "Exception during rename: " + std::string(e.what()));
        }
    }
    
    // 7. 搜索文件 - 支持正则表达式
    std::vector<std::string> search_files(const std::string& directory, 
                                         const std::string& pattern, 
                                         bool recursive = true) {
        std::vector<std::string> results;
        
        try {
            std::regex regex_pattern(pattern);
            search_files_recursive(fs::path(directory), regex_pattern, results, recursive);
        } catch (const std::regex_error& e) {
            std::cerr << "Invalid regex pattern: " << e.what() << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error during search: " << e.what() << std::endl;
        }
        
        return results;
    }
   
    // 8. 工具函数：检查路径是否存在
    bool exists(const std::string& path) {
        return fs::exists(fs::path(path));
    }
    
    // 9. 工具函数：检查是否为目录
    bool is_directory(const std::string& path) {
        return fs::exists(fs::path(path)) && fs::is_directory(fs::path(path));
    }
    
    // 10. 工具函数：检查是否为文件
    bool is_file(const std::string& path) {
        return fs::exists(fs::path(path)) && fs::is_regular_file(fs::path(path));
    }
    
    // 11. 工具函数：获取文件大小
    std::uintmax_t get_file_size(const std::string& file_path) {
        try {
            return fs::file_size(fs::path(file_path));
        } catch (const std::exception&) {
            return static_cast<std::uintmax_t>(-1);
        }
    }
    
    // 12. 工具函数：获取绝对路径
    std::string get_absolute_path(const std::string& path) {
        try {
            return fs::absolute(fs::path(path)).string();
        } catch (const std::exception&) {
            return path;
        }
    }
    
    // 13. 获取某个文件夹下的所有目录，返回绝对路径
    std::vector<std::string> get_directories(const std::string& directory, bool recursive = false) {
        std::vector<std::string> results;
        
        try {
            fs::path dir_path(directory);
            if (!fs::exists(dir_path) || !fs::is_directory(dir_path)) {
                std::cerr << "Error: Directory does not exist or is not a directory: " << directory << std::endl;
                return results;
            }
            
            if (recursive) {
                // 使用递归迭代器
                for (const auto& entry : fs::recursive_directory_iterator(dir_path)) {
                    if (fs::is_directory(entry)) {
                        results.push_back(fs::absolute(entry.path()).string());
                    }
                }
            } else {
                // 使用非递归迭代器
                for (const auto& entry : fs::directory_iterator(dir_path)) {
                    if (fs::is_directory(entry)) {
                        results.push_back(fs::absolute(entry.path()).string());
                    }
                }
            }
            
        } catch (const std::exception& e) {
            std::cerr << "Error during directory enumeration: " << e.what() << std::endl;
        }
        
        return results;
    }
    
    // 14. 获取某个文件夹下的所有文件，返回绝对路径
    std::vector<std::string> get_files(const std::string& directory, bool recursive = false) {
        std::vector<std::string> results;
        
        try {
            fs::path dir_path(directory);
            if (!fs::exists(dir_path) || !fs::is_directory(dir_path)) {
                std::cerr << "Error: Directory does not exist or is not a directory: " << directory << std::endl;
                return results;
            }
            
            if (recursive) {
                // 使用递归迭代器
                for (const auto& entry : fs::recursive_directory_iterator(dir_path)) {
                    if (fs::is_regular_file(entry)) {
                        results.push_back(fs::absolute(entry.path()).string());
                    }
                }
            } else {
                // 使用非递归迭代器
                for (const auto& entry : fs::directory_iterator(dir_path)) {
                    if (fs::is_regular_file(entry)) {
                        results.push_back(fs::absolute(entry.path()).string());
                    }
                }
            }
            
        } catch (const std::exception& e) {
            std::cerr << "Error during file enumeration: " << e.what() << std::endl;
        }
        
        return results;
    }
    
    // 15. 获取某个文件夹下的所有项目（文件和目录），返回绝对路径
    struct DirectoryEntry {
        std::string path;
        bool is_directory;
        std::uintmax_t size;  // 对文件有效，目录为0
        
        DirectoryEntry(const std::string& p, bool is_dir, std::uintmax_t s = 0) 
            : path(p), is_directory(is_dir), size(s) {}
    };
    
    std::vector<DirectoryEntry> get_directory_contents(const std::string& directory, bool recursive = false) {
        std::vector<DirectoryEntry> contents;
        
        try {
            fs::path dir_path(directory);
            if (!fs::exists(dir_path) || !fs::is_directory(dir_path)) {
                std::cerr << "Error: Directory does not exist or is not a directory: " << directory << std::endl;
                return contents;
            }
            
            if (recursive) {
                // 使用递归迭代器
                for (const auto& entry : fs::recursive_directory_iterator(dir_path)) {
                    std::string abs_path = fs::absolute(entry.path()).string();
                    if (fs::is_regular_file(entry)) {
                        std::uintmax_t file_size = 0;
                        try {
                            file_size = fs::file_size(entry.path());
                        } catch (const std::exception&) {
                            file_size = 0;  // 如果无法获取大小，设为0
                        }
                        contents.emplace_back(abs_path, false, file_size);

                    } else if (fs::is_directory(entry)) {
                        contents.emplace_back(abs_path,true,0);
                    }
                }
            } else {
                // 使用非递归迭代器
                for (const auto& entry : fs::directory_iterator(dir_path)) {
                    std::string abs_path = fs::absolute(entry.path()).string();
                    if (fs::is_regular_file(entry)) {
                        std::uintmax_t file_size = 0;
                        try {
                            file_size = fs::file_size(entry.path());
                        } catch (const std::exception&) {
                            file_size = 0;  // 如果无法获取大小，设为0
                        }
                        contents.emplace_back(abs_path, false, file_size);
                    } else if (fs::is_directory(entry)) {
                        contents.emplace_back(abs_path,true,0);
                    }
                }
            }
            
        } catch (const std::exception& e) {
            std::cerr << "Error during directory content enumeration: " << e.what() << std::endl;
        }
        
        return contents;
    }
};

#endif // FILE_UTILS_H